//
// Created by tang on 2022/3/29.
//

#include "log.hpp"
#include <cstdio>
#include <cstdarg>
#include <cassert>
#include <cstring>
#include <ctime>
#include <unistd.h>

static int put_time(char *buffer, size_t len) {
    time_t timer;
    struct tm* tm_info;

    timer = time(nullptr);
    tm_info = localtime(&timer);

    len = strftime(buffer, len, "[%Y-%m-%d %H:%M:%S]", tm_info);

    return static_cast<int>(len);
}

static void platform_console_write(const char* message, int colour) {
    // FATAL,ERROR,WARN,INFO,DEBUG,TRACE
    const char* colour_strings[] = {"0;41", "1;31", "1;33", "1;32", "1;34", "1;30"};
    printf("\033[%sm%s\033[0m", colour_strings[colour], message);
}
static void platform_console_write_error(const char* message, int colour) {
    // FATAL,ERROR,WARN,INFO,DEBUG,TRACE
    const char* colour_strings[] = {"0;41", "1;31", "1;33", "1;32", "1;34", "1;30"};
    printf("\033[%sm%s\033[0m", colour_strings[colour], message);
}

void log_message(LogLevel level, const char *fmt, ...) {
    static const char *desc[LogLevel::CNT] = {
            "[ TRACE  ]",
            "[ DEBUG  ]",
            "[  INFO  ]",
            "[  WARN  ]",
            "[ ERROR  ]",
            "[CRITICAL]",
    };

    assert(level >= TRACE && level < CNT);

    va_list ap;
    va_start(ap, fmt);

    char buff[4096] {0};
    int offset = put_time(buff, sizeof (buff));
    memcpy(buff+offset,desc[level],10);
    offset+=10;
    buff[offset++] = ':';
    offset += vsnprintf(buff+offset, sizeof(buff) - offset - 1, fmt, ap);
    va_end(ap);
    buff[offset] = '\n';

    if (level >= ERROR) {
        platform_console_write_error(buff, CNT - level - 1);
    } else {
        platform_console_write(buff, CNT - level - 1);
    }
}
